<?php

// +----------------------------------------------------------------------
// | 处理user token相关的业务
// +----------------------------------------------------------------------
// | @author fancsen
// +----------------------------------------------------------------------

namespace app\api\service;

use app\common\lib\exception\ApiException;
use app\api\model\User as UserModel; 
use app\common\lib\enum\ScopeEnum;


class UserToken extends Token
{

    protected $app_id;
    protected $app_secret;
    protected $code;
    protected $login_url;

    public function __construct($code)
    {
        $this->app_id = config('wx.app_id');
        $this->app_secret = config('wx.app_secret');
        $this->code = $code;      
        $this->login_url = sprintf(config('wx.login_url'),$this->app_id,$this->app_secret,$code);
    }

    /**
     * 获取微信openid
     */
    public function get()
    {
        $result = curl_get($this->login_url);
        $wxReturn = json_decode($result,true);
        if(empty($wxReturn)){
            throw new Exception("获取session_key及openID异常，微信内部错误");
        }else {
            $loginFail = array_key_exists('errcode',$wxReturn);
            if($loginFail){
                $this->processLoginError($wxReturn);   
            }else {
                return $this->grantToken($wxReturn);
            }
        }
    }


    /**
     * 颁发token
     * 
     */
    private function grantToken($wxReturn)
    {
        // 1拿到openid
        // 2数据库里检查openid是否存在
        // 3如果不存在则新添一条记录
        // 4生成令牌，缓存数据
        // 5把令牌返回到客户端
        // key: 令牌
        // value: wxResult,uid,scope
        $openid = $wxReturn['openid'];

        $user = UserModel::getUserByOpenid($openid);

        if($user){
            $uid = $user->id;   
        }else {
            $uid = $this->addNewUser($openid);

        }

        $cacheValue = $this->prepareCachedValue($wxReturn,$uid);

        $token = $this->saveToCache($cacheValue);

        return $token;
    }

    /**
     * 加入缓存
     */
    private function saveToCache(array $cacheValue)
    {
        $key = self::generateToken();

        $value = json_encode($cacheValue);

        $result = cache($key,$value,config('api.token_expire_in'));

        if(!$result){
            throw new ApiException('服务器缓存异常',404,10005);
        }

        return $key;
    }

    /**
     * 组装缓存数据
     * @param array $wxReturn 微信返回值
     * @param int $uid 用户id
     * @return array 返回新组装的值 [
     *                  openid,
     *                  session_key,
     *                  uid,
     *                  scope,//用户权限
     *              ]
     */
    private function prepareCachedValue($wxReturn,$uid)
    {
        $value = $wxReturn;
        $value['uid'] = $uid;
        $value['scope'] = ScopeEnum::User;//用户权限

        return $value;
    }

    /**
     * 添加新用户
     * @param string $openid 用户openid
     * @return int 用户id
     */
    private function addNewUser($openid)
    {
        try{
            $user = UserModel::create([
                'openid'=>$openid
            ]);
        }catch(\Exception $e){
            throw new \Exception($e->getMessage());
            
        }
        return $user->id;
    }

    private function processLoginError($wxReturn){
        throw new ApiException(
                $wxReturn['errmsg'],
                401,
                $wxReturn['errcode']
        );
    }
}
